package com.dat255.internalstorage;

import java.util.ArrayList;

import com.dat255.tentatime.Exam;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;

/**
 * This class is used for storing exams local on the 
 * phone's internal storage, a database is used in this case
 * @author Joseph Hejderup
 * @version 1
 */


//TODO: crete internal method for contentvalues
//TODO:
public class InternalStorage implements IStorage {
	
	//global information about the application environment
	private Context context;
	//Instance of the dbHelper
	private DbHelper dbHelper= null;
	//The sqlitedatabase
	private SQLiteDatabase database =null;
	

	
	
	public InternalStorage(Context context){
		
		this.context = context;

	}

	/**
	 * This internal method open a writable and readable database, with 
	 * write and read access to the database
	 * @throws SQLiteException, if the database cannot be opened
	 */
	private  void openWritable() throws SQLiteException{
		
		dbHelper = new DbHelper(context);
		// a writable object of the database will be returned
		database = dbHelper.getWritableDatabase();
		
	}

	/**
	 * This internal method will open a readable database, 
	 * with read only access
	 * @throws SQLiteException, if the database cannot be opened
	 */
	private void openReadable() throws SQLiteException{
		
		dbHelper = new DbHelper(context);
		// a read-only object of the database will be returned
		database = dbHelper.getReadableDatabase();
		
	}
	/**
	 * This method will close the database, 
	 */
	private void close(){
		
		database.close();
		
	}
	/**
	 * This method will add an exam to the system
	 * @param: The exam to be added
	 */
	public boolean addExam(Exam exam) {
		
		//Open a read/write database
		openWritable();
		
		//TODO: check that no field in the exam object is set to string empty
		ContentValues values = new ContentValues();
        //map the values from the exam object with respective column in the database
		//values.put(DbHelper.getKeyRowid(), );
        values.put(DbHelper.getColCourseId(), exam.getCourseID());
        values.put(DbHelper.getColCourseName(), exam.getCourseName());
        values.put(DbHelper.getColCoursePlace(), exam.getPlace());
        values.put(DbHelper.getColCourseTime(), exam.getTime());
        values.put(DbHelper.getColCourseDate(), exam.getDate());
        
       //insert the content values in the database, if successful a rowid will be returned and status set to true
       //if -1 is returned, that is an indication of an error, status set to false
		boolean status = database.insert(DbHelper.getExamlistTableName(), null, values)  > 0;
        
		//Close the database
		close();
		
		return status;
		
		
	}
	/**
	 * Returns the exam according to corresponding rowid(position)
	 * @param the row id
	 * @return The selected exam, or null if the exam couldn't be found
	 */
	public Exam getExam(String courseid) {
		
		ArrayList<Exam> exams = this.allExams();
		
		Exam findExam = null;
		
		for(Exam exam: exams){
			
			
			if(exam.getCourseID().equals(courseid)){
				
				findExam = exam;
				break;
				
			}
			
		}
		 return findExam;
	
	}
	/**
	 * Remove the exam at the specified position(rowid) in the database
	 */
	public boolean removeExam(String courseid) {
		

		//open database
		this.openWritable();
		
		//Removes the exam based on the course id
		boolean status = database.delete(DbHelper.getExamlistTableName(), DbHelper.getColCourseId() + "=?", new String[] { courseid }) > 0;
		//close the database
		this.close();
		
		return status;
	
	}

	/**
	 * This method will change an exam on the system
	 * @param The changed exam
	 */
	public boolean changeExam(Exam exam, String courseid) {

		//Open the database
		this.openWritable();
		
		ContentValues updateValues = new ContentValues();
        //Extract the content on the new exam object into corresponding column in the database
		
		updateValues.put(DbHelper.getColCourseId(), exam.getCourseID());
		updateValues.put(DbHelper.getColCourseName(), exam.getCourseName());
		updateValues.put(DbHelper.getColCoursePlace(), exam.getPlace());
		updateValues.put(DbHelper.getColCourseTime(), exam.getTime());
		updateValues.put(DbHelper.getColCourseDate(), exam.getDate());
		
		 //insert the content values in the database, if successful a rowid will be returned and status set to true
	     //if -1 is returned, that is an indication of an error, status set to false
		boolean status = database.update(DbHelper.getExamlistTableName(), updateValues, DbHelper.getColCourseId()+"=?", new String[] { courseid }) > 0;
		//close the database
		close();
		
		return status;
		
	}

	/**
	 * Checks if the storage is empty
	 */
	public boolean isEmpty() {
		
		Cursor curNumofExams = this.fetchAllExams();
		curNumofExams.moveToFirst();
		
		//getcount: numofrows
		this.close();
		boolean empty = curNumofExams.getCount() <= 0;
		curNumofExams.close();
		return empty;
		
	}

	@Override
	public boolean containsExam(Exam exam) {
		//open database
		this.openWritable();
		
		Cursor mCursor = database.query(DbHelper.getExamlistTableName(),new String[] { 
			DbHelper.getColCourseId(), 
			DbHelper.getColCourseName(), 
			DbHelper.getColCoursePlace(), 
			DbHelper.getColCourseTime(), DbHelper.getColCourseDate()}
		  , DbHelper.getColCourseId()+"=?", new String[] { exam.getCourseID() }, null, null, null);
		
		boolean exists = (mCursor.getCount() > 0);
		mCursor.close();
		this.close();
		return exists;
	
	
	}
	
	/**
	 * This method will return a list of all the exams in the database
	 */
	public ArrayList<Exam> allExams() {
		
		//get all the exams
		Cursor curExams = fetchAllExams();
		
		
		//move to the first row
		curExams.moveToFirst();
		
		ArrayList<Exam> eList = new ArrayList<Exam>();
		
		//loop through the cursor object and add all the object to the arraylist
		while (curExams.isAfterLast() == false) {
	            
			
			eList.add(new Exam(curExams.getString(curExams.getColumnIndex(DbHelper.getColCourseId())), 
					curExams.getString(curExams.getColumnIndex(DbHelper.getColCourseName())), 
					curExams.getString(curExams.getColumnIndex(DbHelper.getColCourseTime())), 
					curExams.getString(curExams.getColumnIndex(DbHelper.getColCourseDate())), 
					curExams.getString(curExams.getColumnIndex(DbHelper.getColCoursePlace()))));
			
			curExams.moveToNext();
	        }
		
		curExams.close();
		
		return eList;
		
		
		
	}
	/**
	 * This method will put all entries in the database and store it as a cursor object
	 * @return
	 */
	private Cursor fetchAllExams() {
		
		//open database	
		this.openWritable();
			
			return database.query(DbHelper.getExamlistTableName(), new String[] {
				DbHelper.getColCourseId(), DbHelper.getColCourseName(), DbHelper.getColCoursePlace(), DbHelper.getColCourseTime(), DbHelper.getColCourseDate()  }, null, null, null,
				null, null);
			
			
	}
	
	/**
	 * This method will remove specified  exam object 
	 */
	public boolean removeExam(Exam exam) {
		
		//open database
		this.openWritable();
		
		//Removes the exam based on the course id
		boolean status = database.delete(DbHelper.getExamlistTableName(), DbHelper.getColCourseId() + "=?", new String[] { exam.getCourseID() }) > 0;
		//close the database
		this.close();
		
		return status;
		
		
	}
	
	/**
	 * Removes all the exams from the system
	 */
	public boolean removeAllExams() {
		this.openWritable();
		
		boolean removeStatus = database.delete(DbHelper.getExamlistTableName(),null,null) == 1 ;
		
		close();
		
		return removeStatus;
		
		
	}
	
	public long NumberOfRows() {
	    String sql = "SELECT COUNT(*) FROM " + DbHelper.getExamlistTableName();
	    SQLiteStatement statement = database.compileStatement(sql);
	    long count = statement.simpleQueryForLong();
	    return count;
	
	
	}
	
	

}
